//
// 设备连接接待
//

package worker

import (
	"net"
	"io"
	"strings"
	"time"
	"encoding/json"
)

//
// 设备与服务器连接，服务器端的接待者
//
type Worker struct {
	conn    net.Conn       	// 设备连接

	dev  	*DeviceServices 	// 管理设备服务列表

	devId	string			// 关联设备的ID

	sevDev  *SevDevice     	// 设备服务

	post    chan []byte    	// 服务端推送给设备终端的信息
	message chan []byte    	// 设备终端发送给服务器的信息

	request chan []byte    	// 家庭对设备的操作请求
	notify  chan []byte    	// 设备向家庭推送的状态通知

	end		chan bool		// 应用外部主动断开连接
}

//
// 处理设备连接
//
func HandleConn(conn net.Conn) {
	defer conn.Close()

	// 处理不正常连接
	if strings.Contains(conn.RemoteAddr().String(), "127.0.0.1") {
		return
	}

	w := Worker{
		dev: nil,
		devId: "",
		conn: conn,
	}

	evtLogger.Notice("remote: %s connected", conn.RemoteAddr().String())
	defer evtLogger.Notice("remote: %s disconnected", conn.RemoteAddr().String())

	// 接收设备消息
	w.message = make(chan []byte, 2)
	go w.revMessage()

	// 推送给设备的消息
	w.post = make(chan []byte, 2)
	go w.postMessage()
	defer close(w.post)

	w.end = make(chan bool, 1)

	// 家庭发送的请求
	w.request = make(chan []byte, 2)

	// 推送给家庭的状态信息
	w.notify = make(chan []byte, 2)

	// 接待者的基本服务(设备服务)
	w.sevDev = &SevDevice{
		Service{
			Post: w.post,
			Notify: w.notify,
		},
	}

	// 断开连接之前，设备离线
	defer w.handleOffline()

	// 接待者处理业务逻辑
	for {
		select {

		// 设备发送过来的消息
		case msg, ok := <- w.message:
			if ok {
				w.handleMessage(msg)
			} else {
				return
			}

		// 家庭发送给设备的消息
		case request, ok := <- w.request:
			if ok {
				w.handleRequest(request)
			}

		// 处理设备产生的通知消息
		case notify, ok := <- w.notify:
			if ok {
				w.handleNotify(notify)
			}

		case <- w.end:
			return

		// 超时
		case <- time.After(time.Second * 30):
			return
		}
	}
}

//
// 接收设备端发送来的消息
//
func (w *Worker) revMessage() {
	buffer := make([]byte, 1024)
	for {
		n, err := w.conn.Read(buffer)
		if err != nil || err == io.EOF {
			devLogger.Error("remote: ", w.conn.RemoteAddr(), " read err")
			close(w.message)
			return
		} else {
			// 处理粘包问题
			msg_arr := strings.Split(string(buffer[:n]), "\n")
			for _, msg := range msg_arr {
				if msg != "" {
					w.message <- []byte(msg)
				}
			}
		}
	}
}

//
// 向设备终端推送消息
//
func (w *Worker) postMessage() {
	for msg := range w.post {
		devLogger.Info("dev:%s  post:%s", w.devId, string(msg))
		w.conn.Write(msg)
	}
}

//
// 处理设备消息
//
func (w *Worker) handleMessage(buffer []byte) error {
	// 消息解析
	devLogger.Info("dev:%s  msg:%s", w.devId, string(buffer))
	var msg SevMessage
	if err := json.Unmarshal(buffer, &msg); err != nil {
		return err
	}

	data, err := json.Marshal(msg.Message)
	if err != nil {
		return err
	}

	// 截取设备消息
	if msg.SevId == SEV_DEV_ID {
		return w.sevDev.Message(data)
	}

	// 交由设备服务列表处理
	if w.dev == nil {
		return nil
	}

	if sev, ok := w.dev.SevMaps[msg.SevId]; ok {
		sev.Message(data)
	}

	return nil
}

//
// 处理家庭消息推送信息
//
func (w *Worker) handleNotify(buffer []byte) error {

	// 截取设备登入登出的消息
	var notify Notify
	if err := json.Unmarshal(buffer, &notify); err != nil {
		return err
	}

	// 截取设备在线的消息
	if notify.Notify.Type == SEV_DEV_NOTIFY_LOGIN && notify.SevId == SEV_DEV_ID {
		if id, ok := notify.Notify.Date.(string); ok {
			w.handleOnline(id)
			notify.Notify.Date = nil
		}
	}

	notify.DevId = w.devId
	notify_buf, _ := json.Marshal(notify)

	// 将通知消息交给设备中心中转出去
	DeviceNotify(w.devId, notify_buf)

	return nil
}

//
// 处理来自家庭的控制请求
//
func (w *Worker) handleRequest(buffer []byte) error {
	devLogger.Info("request:%s", string(buffer))

	var request Request
	err := json.Unmarshal(buffer, &request)
	if err != nil {
		return err
	}

	request_data, err := json.Marshal(request.Request)
	if err != nil {
		return err
	}

	// 查找对于的服务进行处理
	if w.dev == nil {
		return nil
	}
	if sev, ok := w.dev.SevMaps[request.SevId]; ok {
		return sev.Request(request_data)
	}
	return nil
}

//
// 接待者处理设备上线
//
func (w *Worker) handleOnline(devId string) error {
	w.devId = devId

	// 设备在线
	w.dev = DeviceOnline(w.devId, w)

	return nil
}

//
// 主动断开连接
//
func (w *Worker) Destroy() error {
	w.end <- true
	return nil
}


//
// 接待者处理设备离线
//
func (w *Worker) handleOffline() error {

	// 离线之前，产生设备离线通知
	if w.devId != "" {

		err := DeviceOffline(w.devId, w)
		if err != nil {
			devLogger.Notice("device: %s has already reconnected!", w.devId)
			return nil
		}

		// 发送设备离线通知
		if notify, err := w.sevDev.LogoutNotify(w.devId); err == nil {
			DeviceNotify(w.devId, notify)
		}
	}
	return nil
}


//
// 接待者对外的操作请求接口
//
func (w *Worker) Request(buffer []byte) error {
	w.request <- buffer
	return nil
}

